package com.hsgene.common.util.http;

import org.apache.http.HttpEntity;
import org.apache.http.NameValuePair;
import org.apache.http.client.entity.UrlEncodedFormEntity;
import org.apache.http.client.methods.CloseableHttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpPost;
import org.apache.http.client.methods.HttpPut;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.entity.StringEntity;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;
import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.net.ssl.SSLContext;
import java.nio.charset.Charset;
import java.util.List;

/**
 * http连接池
 *
 * @author wxf
 * @date 2018/8/13 17:14
 **/
@Component
public class HttpConnectionManager {

    /**
     * Log
     */
    private static final Logger LOGGER = LogManager.getLogger(HttpConnectionManager.class);

    private static PoolingHttpClientConnectionManager connectionManager = null;

    private static CloseableHttpClient httpClient = null;

    @PostConstruct
    private void init() {
        try {
            LayeredConnectionSocketFactory lcsf = new SSLConnectionSocketFactory(SSLContext.getDefault());
            Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                    .register("https", lcsf)
                    .register("http", new PlainConnectionSocketFactory())
                    .build();
            connectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
            //最大连接数
            connectionManager.setMaxTotal(200);
            //默认的每个路由的最大连接数
            connectionManager.setDefaultMaxPerRoute(20);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static PoolingHttpClientConnectionManager getConnectionManager() {
        return connectionManager;
    }

    public static CloseableHttpClient getHttpClient() {
        CloseableHttpClient httpClient = HttpClients.custom().setConnectionManager(connectionManager)
                .setConnectionManagerShared(true)
                .build();
        return httpClient;
    }

    /**
     * Get请求
     * @param url
     * @param charset
     * @return
     */
    public String doGet(String url, String charset) {
        String result = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = getHttpClient();
            HttpGet request = new HttpGet(url);
            response = httpClient.execute(request);
            result = EntityUtils.toString(response.getEntity(), charset);
            LOGGER.info("get请求结果：" + result);
        } catch (Exception e) {
            LOGGER.error("http get request is error", e);
        } finally {
            closeConnection(httpClient, response);
        }
        return result;
    }

    /**
     * post
     *
     * @param o       参数对象
     * @param url     地址
     * @param charset 编码
     * @return
     */
    public String doPost(Object o, String url, String charset) {
        String result = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = getHttpClient();
            HttpPost post = new HttpPost(url);
            if (o instanceof String) {
                StringEntity entity = new StringEntity(o.toString(), charset);
                post.addHeader("Content-type","application/json; charset=utf-8");
                post.setHeader("Accept", "application/json");
                post.setEntity(entity);
            }
            if (o instanceof List) {
                HttpEntity entity = new UrlEncodedFormEntity((List<? extends NameValuePair>) o,charset);
                post.setEntity(entity);
            }
            response = httpClient.execute(post);
            result = EntityUtils.toString(response.getEntity(), charset);
            LOGGER.info("post请求结果：" + result);
        } catch (Exception e) {
            LOGGER.error("post request query is error...", e);
        } finally {
            closeConnection(httpClient, response);
        }
        return result;
    }

    /**
     * Put请求
     * @param o
     * @param url
     * @param charset
     * @return
     */
    public String doPut(Object o, String url, String charset) {
        String result = null;
        CloseableHttpResponse response = null;
        try {
            httpClient = getHttpClient();
            HttpPut put = new HttpPut(url);
            //put.setHeader("Content-type", "application/json");
            if (o != null) {
                StringEntity entity = new StringEntity((String) o);
                entity.setContentEncoding(charset);
                entity.setContentType("application/json");
                put.setEntity(entity);
            }
            response = httpClient.execute(put);
            result = EntityUtils.toString(response.getEntity(), charset);
            LOGGER.info("put请求结果：" + result);
        } catch (Exception e) {
            LOGGER.error("put request query is error...", e);
        } finally {
            closeConnection(httpClient, response);
        }
        return result;
    }

    private void closeConnection(CloseableHttpClient httpClient, CloseableHttpResponse response) {
        try {
            if (response != null) {
                response.close();
            }
            httpClient.close();
        } catch (Exception e) {
            LOGGER.error("close http post is error", e);
        }
    }
}
